using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Threading;
using System.Windows.Forms;

using MT.eVotePRS.Common;
using MT.eVotePRS.Device;
using MT.eVotePRS.Model;

namespace MT.eVotePRS.UI
{
    public partial class frmCheckIn : Form
    {
        object obj;
        StudentInfo studentInfo;
        InventoryTxn inventoryTxn;

        protected override void WndProc(ref Message m)
        {
            int devCount;

            if (m.Msg == Device.Native.Win32Message.WM_DEVICECHANGE)
            {
                switch ((int)m.WParam)
                {
                    case Device.Native.Win32Message.DBT_DEVICEARRIVAL:
                    case Device.Native.Win32Message.DBT_DEVICEREMOVECOMPLETE:

                        devCount = Program.ArsAPIHelper.ArsDeviceConnected();

                        if (0 == devCount)
                        {
                            if (Program.ArsAPIHelper.Processing)
                            {
                                Program.ArsAPIHelper.StopProcess();
                            }
                            DialogBox.boxWarning(string.Format("Receiver Count={0}, Please prepare the receiver first.", devCount.ToString()), "Warning!");
                        }
                        Thread.Sleep(10);
                        break;
                    default:
                        break;
                }
            }
            base.WndProc(ref m);
        }

        public frmCheckIn()
        {
            InitializeComponent();
            timer2.Start();

            obj = new object();
            studentInfo = new StudentInfo();
            inventoryTxn = new InventoryTxn();
        }

        private void frmCheckIn_FormClosing(object sender, FormClosingEventArgs e)
        {
            Program.ArsAPIHelper.StopProcess();
        }

        private void frmCheckIn_Load(object sender, EventArgs e)
        {
            this.txtDatetime.Text = DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss");

            // Since we are start this program, it would like to detect the device once.
            Message m = new Message();
            m.Msg = Device.Native.Win32Message.WM_DEVICECHANGE;
            m.WParam = (System.IntPtr)Device.Native.Win32Message.DBT_DEVICEARRIVAL;

            WndProc(ref m);

            int ret = Program.ArsAPIHelper.RegisterDeviceNotify((Int32)this.Handle);
            if (ret > 0)
            {
                Program.ArsAPIHelper.StartProcess();
            }

            txtHandsetID.Focus();
            txtHandsetID.SelectAll();
        }

        private void timer2_Tick(object sender, EventArgs e)
        {
            this.txtDatetime.Text = DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss");
        }

        private void btnClose_Click(object sender, EventArgs e)
        {
            if (txtStudentID.Text != string.Empty || txtHandsetID.Text != string.Empty
                || txtRemark.Text != string.Empty || txtStudentName.Text != string.Empty
                || txtStatus.Text != string.Empty)
            {
                if (DialogBox.boxConfirmNo("Are you sure to abort the current action?") == DialogResult.No)
                    return;
            }

            this.Close();
            this.Dispose();
        }
        
        private void btnConfirm_Click(object sender, EventArgs e)
        {
            if (inventoryTxn != null && inventoryTxn.Id > 0)
            {
                if (!isValidate())
                    return;
                
                try
                {
                    // If the student have check-out 2 keypads, and return the second handset now, then it have to check whether the student have been conduct payment or not.
                    // 1.return the current keypad

                    // 2.update the previous keypad to lost

                    string dateTime = DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss");

                    InventoryTxn inventTxn = inventoryTxn;
                    inventTxn.StudentID = txtStudentID.Text.Trim();
                    inventTxn.HandsetID = txtHandsetID.Text.Trim();
                    inventTxn.Status = Presentation.Util.Constants.Status_CheckIn.Id;
                    inventTxn.UserEvent = Presentation.Util.Constants.Status_CheckIn.StatusDesc;
                        
                    inventTxn.Remark = txtRemark.Text;
                    inventTxn.TxnTime = DateTime.Now;
                    inventTxn.IsOverride = false;
                    inventTxn.OverrideStatus = Presentation.Util.Constants.Status_Nil.Id;

                    object objTxnId = new Presentation.Logic.InventoryTxnActions().CreateNewTxn(inventTxn);

                    if (objTxnId != null && Convert.ToInt32(objTxnId )> 0)
                    {
                        DialogBox.boxInfo("Completed !");

                        txtStudentID.Text = "";
                        txtHandsetID.Text = "";
                        txtDatetime.Text = "";
                        txtRemark.Text = "";
                        txtStudentName.Text = "";
                        txtStatus.Text = "";
                    }
                    else
                    {
                        DialogBox.boxWarning("Update failed!", "Warning!");
                        return;
                    }
                }
                catch (Exception ex)
                {
                    DialogBox.boxWarning("Exception: " + ex.Source + "; " + "Message: " + ex.Message, "Warning!");
                }
            }

            txtHandsetID.Enabled = true;
            txtStudentID.Enabled = true;
        }

        delegate void _dataReceived(object sender, ARSEventArgs e);
        void dataReceiver_DataReceived(object sender, ARSEventArgs e)
        {
            if (this.InvokeRequired)
            {
                this.Invoke(new _dataReceived(dataReceiver_DataReceived), sender, e);
                return;
            }

            HandsetData keypadData = (HandsetData)e.ReceivedData;
            switch (keypadData.CommandCode)
            {
                case ARSCommandCode.STUDENT_JOIN:
                    checkHandsetCanChecnIn(keypadData.MacStr);
                    break;

                default:
                    break;
            }
        }

        private void checkHandsetCanChecnIn(string handsetId)
        {
            try
            {
                lock (obj)
                {
                    txtStudentID.Text = "";
                    txtHandsetID.Text = handsetId;
                    txtRemark.Text = "";
                    txtStudentName.Text = "";
                    txtStatus.Text = "";

                    btnConfirm.Enabled = false;

                    InventoryTxn inventTxn = new Presentation.Logic.InventoryTxnActions().CheckHandsetStatus(handsetId );

                    if (inventTxn != null && inventTxn.Id > 0)
                    {
                        if (inventTxn.IsOverride)
                        {
                            DialogBox.boxWarning(string.Format("The Handset \"{0}\" can't be Checked in!", handsetId), "Warning!");
                            return;
                        }
                        else
                        {
                            if (inventTxn.Status != Presentation.Util.Constants.Status_CheckOut.Id && inventTxn.Status != Presentation.Util.Constants.Status_Lost.Id)
                            {
                                // if check out or lost, then it can be check in. else not allow
                                DialogBox.boxWarning( string.Format("The handset \"{0}\" isn't Checked Out or Lost, it can't be Checked in!", handsetId), "Warning!");
                                return;
                            }

                            inventoryTxn = inventTxn;

                            txtHandsetID.Text = inventoryTxn.HandsetID;
                            txtStudentID.Text = inventoryTxn.StudentID;
                            txtStatus.Text = inventoryTxn.UserEvent;
                            txtStudentName.Text = "";

                            studentInfo = new Presentation.Logic.StudentActions().FindStudentByNo(inventTxn.StudentID);
                            if (studentInfo != null)
                            {
                                txtStudentName.Text = studentInfo.StudentName;
                            }

                            txtRemark.Text = "";
                            txtRemark.SelectAll();

                            btnConfirm.Enabled = true;
                        }
                    }
                    else
                    {
                        btnConfirm.Enabled = false;
                        txtRemark.ReadOnly = true;

                        txtStudentID.Text = string.Empty;
                        txtStudentName.Text = string.Empty;
                        txtStatus.Text = string.Empty;

                        DialogBox.boxWarning(string.Format("The Handset \"{0}\" can't be Checked in!", handsetId), "Warning!");
                        return;
                    }
                }
            }
            catch (Exception ex)
            {
                DialogBox.boxWarning("Exception: " + ex.Source + "; " + "Message: " + ex.Message);
            }
        }

        bool isValidate()
        {
            bool ret = true;
            // keypad id
            if (string.IsNullOrEmpty(txtHandsetID.Text.Trim()))
            {
                DialogBox.boxWarning("Invalid Handset ID!", "Warning!");
                txtHandsetID.Select();
                return false;
            }
            
            // student id
            if (string.IsNullOrEmpty(txtStudentID.Text.Trim()))
            {
                DialogBox.boxWarning("Invalid Student ID!", "Warning!");
                txtStudentID.Select();
                return false;
            }

            return ret;
        }
    }
}